package enduringLink;

import enduringLink.call.*;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import reader.PartAndLineItemHandler;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.util.Properties;

//负责控制的那个实例与远程3个实例建立长连接，客户端
//使用netty框架负责连接的建立和监听
public class ClientPool {
    NioSocketChannel[] clients;

    //建立连接
    public ClientPool(){
        clients = new NioSocketChannel[3];
        Properties properties = new Properties();
        try {
            InputStream is = PartAndLineItemHandler.class.getClassLoader().getResourceAsStream("address.properties");
            properties.load(is);
            for (int i = 1; i <=3 ; i++) {
                int port = Integer.parseInt(properties.getProperty("port_enduring" + i));
                String hostname = properties.getProperty("hostname" + i);
                InetSocketAddress address = new InetSocketAddress(hostname, port);
                clients[i - 1] = create(address);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private NioSocketChannel create(InetSocketAddress address){

        //创建RPC调用的对象
        MyStartLoad myStartLoad = new MyStartLoad();
        MyStartSelect myStartSelect = new MyStartSelect();
        MyQuantityHandle myQuantityHandle = new MyQuantityHandle();
        MyTransfer myTransfer = new MyTransfer(myQuantityHandle);

        //以键值对的方式保存创建的对象
        Dispatcher dis = Dispatcher.getDis();
        dis.register(StartLoad.class.getName(), myStartLoad);
        dis.register(StartSelect.class.getName(), myStartSelect);
        dis.register(QuantityHandle.class.getName(), myQuantityHandle);
        dis.register(Transfer.class.getName(), myTransfer);

        //基于 netty 的客户端创建方式
        NioEventLoopGroup clientWorker = new NioEventLoopGroup(1);
        Bootstrap bs = new Bootstrap();
        ChannelFuture connect = bs.group(clientWorker)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        p.addLast(new RequestDecode());
                        p.addLast(new RequestHandler(dis));
                    }
                }).connect(address);

        try {
            NioSocketChannel client = (NioSocketChannel)connect.sync().channel();
            return client;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;


    }

    /*
     * @Description: 获取与某个远程实例建立的网络连接
     * @param instanceId : 实例序号
     * @return: {@link io.netty.channel.socket.nio.NioSocketChannel}
     * @author: xff
     * @Date: 2022/7/5
     */
    public NioSocketChannel getClientByInstanceId(int instanceId){
        return clients[instanceId - 1];
    }

}
